﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Xml;

namespace SHomeWorkshop.LunarPresentation.Expressions
{
    public class Triangle : CanvasExpression
    {
        public Triangle(SubPanel rootPanel, SubPanel parentPanel, Editor editor)
            : base(rootPanel, parentPanel, editor)
        {
            //绘制三个主子面板的外接圆。
            topEllipse = new Ellipse();
            topEllipse.StrokeThickness = 2;
            topEllipse.Stroke = ExForeground;
            topEllipse.Fill = System.Windows.Media.Brushes.Transparent;
            topEllipse.Cursor = Cursors.Hand;
            topEllipse.MouseRightButtonDown += Ellipse_MouseRightButtonDown;
            topEllipse.MouseLeftButtonDown += Ellipse_MouseLeftButtonDown;
            topEllipse.MouseLeftButtonUp += Ellipse_MouseLeftButtonUp;

            leftEllipse = new Ellipse();
            leftEllipse.StrokeThickness = 2;
            leftEllipse.Stroke = ExForeground;
            leftEllipse.Fill = System.Windows.Media.Brushes.Transparent;
            leftEllipse.Cursor = Cursors.Hand;
            leftEllipse.MouseRightButtonDown += Ellipse_MouseRightButtonDown;
            leftEllipse.MouseLeftButtonDown += Ellipse_MouseLeftButtonDown;
            leftEllipse.MouseLeftButtonUp += Ellipse_MouseLeftButtonUp;

            rightEllipse = new Ellipse();
            rightEllipse.StrokeThickness = 2;
            rightEllipse.Stroke = ExForeground;
            rightEllipse.Fill = System.Windows.Media.Brushes.Transparent;
            rightEllipse.Cursor = Cursors.Hand;
            rightEllipse.MouseRightButtonDown += Ellipse_MouseRightButtonDown;
            rightEllipse.MouseLeftButtonDown += Ellipse_MouseLeftButtonDown;
            rightEllipse.MouseLeftButtonUp += Ellipse_MouseLeftButtonUp;

            basePanel.Children.Add(topEllipse);
            basePanel.Children.Add(leftEllipse);
            basePanel.Children.Add(rightEllipse);

            Canvas.SetZIndex(topEllipse, 1);
            Canvas.SetZIndex(leftEllipse, 2);
            Canvas.SetZIndex(rightEllipse, 3);

            //三个主面板。
            topPanel = new SubPanel(rootPanel, parentPanel, editor, this);
            leftPanel = new SubPanel(rootPanel, parentPanel, editor, this);
            rightPanel = new SubPanel(rootPanel, parentPanel, editor, this);

            topPanel.SizeChanged += eachPanel_SizeChanged;
            leftPanel.SizeChanged += eachPanel_SizeChanged;
            rightPanel.SizeChanged += eachPanel_SizeChanged;

            basePanel.Children.Add(topPanel);
            basePanel.Children.Add(leftPanel);
            basePanel.Children.Add(rightPanel);

            Canvas.SetZIndex(topPanel, 101);
            Canvas.SetZIndex(leftPanel, 102);
            Canvas.SetZIndex(rightPanel, 103);

            //三个附加面板。
            tlPanel = new SubPanel(rootPanel, parentPanel, editor, this);
            trPanel = new SubPanel(rootPanel, parentPanel, editor, this);
            lrPanel = new SubPanel(rootPanel, parentPanel, editor, this);

            Point pt = new Point(0.5, 0.5);
            tlPanel.RenderTransformOrigin = pt;
            trPanel.RenderTransformOrigin = pt;
            tlPanel.RenderTransform = new RotateTransform(-60);
            trPanel.RenderTransform = new RotateTransform(60);

            tlPanel.SizeChanged += eachPanel_SizeChanged;
            trPanel.SizeChanged += eachPanel_SizeChanged;
            lrPanel.SizeChanged += eachPanel_SizeChanged;

            basePanel.Children.Add(tlPanel);
            basePanel.Children.Add(trPanel);
            basePanel.Children.Add(lrPanel);

            Canvas.SetZIndex(tlPanel, 201);
            Canvas.SetZIndex(trPanel, 202);
            Canvas.SetZIndex(lrPanel, 203);

            RefreshSubPanelRelatios();

            this.chineseName = "三角式";
        }

        void Ellipse_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            // 接收拖动来的公式。
            Globals.DropExpression(this);
        }

        void Ellipse_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            //准备拖动公式。
            Globals.dragSourceExpression = this;
            this.Editor.SelectedExpression = this;
            e.Handled = true;
        }

        void Ellipse_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            this.Editor.SelectedExpression = this;
            e.Handled = true;
        }

        private Ellipse topEllipse;

        private Ellipse leftEllipse;

        private Ellipse rightEllipse;

        void eachPanel_SizeChanged(object sender, System.Windows.SizeChangedEventArgs e)
        {
            // 重新计算BasePanel（Canvas）的尺寸。
            double maxDiameter = GetMaxDiameter();

            if (maxDiameter <= 0) return;// 当子面板有一个未实例化时，此变量会返回０.

            double redius = maxDiameter / 2;//半径

            basePanel.Height = maxDiameter + maxDiameter * Math.Sqrt(3) + 20;
            basePanel.Width = maxDiameter * 3 + 20;

            basePanel.InvalidateArrange();
            basePanel.UpdateLayout();

            double halfWidth = basePanel.ActualWidth / 2;
            double halfHeight = basePanel.ActualHeight / 2;

            // 刷新各子面板位置。
            Point topPt = new Point(halfWidth, redius + 10);
            Point leftPt = new Point(redius + 10, basePanel.ActualHeight - redius - 10);
            Point rightPt = new Point(basePanel.ActualWidth - redius - 10, basePanel.ActualHeight - redius - 10);

            Point tlPt = new Point(maxDiameter + 10, halfHeight);
            Point trPt = new Point(basePanel.ActualWidth - maxDiameter - 10, halfHeight);
            Point lrPt = new Point(halfWidth, basePanel.ActualHeight - redius - 10);

            Canvas.SetLeft(topPanel, topPt.X - topPanel.ActualWidth / 2);
            Canvas.SetTop(topPanel, topPt.Y - topPanel.ActualHeight / 2);

            Canvas.SetLeft(leftPanel, leftPt.X - leftPanel.ActualWidth / 2);
            Canvas.SetTop(leftPanel, leftPt.Y - leftPanel.ActualHeight / 2);

            Canvas.SetLeft(rightPanel, rightPt.X - rightPanel.ActualWidth / 2);
            Canvas.SetTop(rightPanel, rightPt.Y - rightPanel.ActualHeight / 2);

            Canvas.SetLeft(tlPanel, tlPt.X - tlPanel.ActualWidth / 2);
            Canvas.SetTop(tlPanel, tlPt.Y - tlPanel.ActualHeight / 2);

            Canvas.SetLeft(trPanel, trPt.X - trPanel.ActualWidth / 2);
            Canvas.SetTop(trPanel, trPt.Y - trPanel.ActualHeight / 2);

            Canvas.SetLeft(lrPanel, lrPt.X - lrPanel.ActualWidth / 2);
            Canvas.SetTop(lrPanel, lrPt.Y - lrPanel.ActualHeight / 2);

            // 重置三个外接圆的位置、大小。
            topEllipse.Width = topEllipse.Height = maxDiameter + 4;
            Canvas.SetLeft(topEllipse, topPt.X - maxDiameter / 2 - 1);
            Canvas.SetTop(topEllipse, topPt.Y - maxDiameter / 2 - 1);

            leftEllipse.Width = leftEllipse.Height = maxDiameter + 4;
            Canvas.SetLeft(leftEllipse, leftPt.X - maxDiameter / 2 - 1);
            Canvas.SetTop(leftEllipse, leftPt.Y - maxDiameter / 2 - 1);

            rightEllipse.Width = rightEllipse.Height = maxDiameter + 4;
            Canvas.SetLeft(rightEllipse, rightPt.X - maxDiameter / 2 - 1);
            Canvas.SetTop(rightEllipse, rightPt.Y - maxDiameter / 2 - 1);
        }

        /// <summary>
        /// 取六个子面板的最大外接圆直径。
        /// </summary>
        /// <returns></returns>
        private double GetMaxDiameter()
        {
            if (topPanel == null || leftPanel == null || rightPanel == null ||
                tlPanel == null | trPanel == null || lrPanel == null) return 0;

            double r = 0;

            double w, h, diameter;

            w = topPanel.ActualWidth; h = topPanel.ActualHeight;
            diameter = Math.Sqrt(w * w + h * h);
            if (r < diameter) r = diameter;

            w = leftPanel.ActualWidth; h = leftPanel.ActualHeight;
            diameter = Math.Sqrt(w * w + h * h);
            if (r < diameter) r = diameter;

            w = rightPanel.ActualWidth; h = rightPanel.ActualHeight;
            diameter = Math.Sqrt(w * w + h * h);
            if (r < diameter) r = diameter;

            w = tlPanel.ActualWidth; h = tlPanel.ActualHeight;
            diameter = Math.Sqrt(w * w + h * h);
            if (r < diameter) r = diameter;

            w = trPanel.ActualWidth; h = trPanel.ActualHeight;
            diameter = Math.Sqrt(w * w + h * h);
            if (r < diameter) r = diameter;

            w = lrPanel.ActualWidth; h = lrPanel.ActualHeight;
            diameter = Math.Sqrt(w * w + h * h);
            if (r < diameter) r = diameter;

            return r + 8;
        }

        public override Brush ExForeground
        {
            get
            {
                return base.ExForeground;
            }
            set
            {
                UpdateExForegroundWithoutXmlChanging(value);
                UpdateExForegroundToXmlData(value);
                Editor.IsModified = true;
            }
        }

        public override void UpdateExForegroundWithoutXmlChanging(Brush value)
        {
            base.UpdateExForegroundWithoutXmlChanging(value);

            //base.exForeground = value;//基类方法中有。

            this.leftEllipse.Stroke = value;
            this.rightEllipse.Stroke = value;
            this.topEllipse.Stroke = value;
        }

        protected override void BuildChildren()
        {
            base.BuildChildren();

            if (this.XmlData == null) return;

            XmlAttribute attrOfHide = this.XmlData.GetAttribute("HideAdditionalPanels");
            if (attrOfHide != null)
            {
                hideAdditionalPanels = Boolean.Parse(attrOfHide.Value);
            }

            XmlNodeList childrenNodes = this.XmlData.SelectNodes("Expression");

            if (childrenNodes == null || childrenNodes.Count <= 0) return;

            foreach (XmlNode node in childrenNodes)
            {
                XmlAttribute attrOfLocation = node.GetAttribute("Location");
                if (attrOfLocation == null) continue;

                switch (attrOfLocation.Value)
                {
                    case "Top":
                        {
                            if (topPanel != null) topPanel.XmlData = node; break;
                        }
                    case "Left":
                        {
                            if (leftPanel != null) leftPanel.XmlData = node; break;
                        }
                    case "Right":
                        {
                            if (rightPanel != null) rightPanel.XmlData = node; break;
                        }
                    case "TopLeft":
                        {
                            if (tlPanel != null) tlPanel.XmlData = node; break;
                        }
                    case "TopRight":
                        {
                            if (trPanel != null) trPanel.XmlData = node; break;
                        }
                    case "LeftRight":
                        {
                            if (lrPanel != null) lrPanel.XmlData = node; break;
                        }
                }
            }

            RefreshSubPanelRelatios();//防止“隐藏附属面板”字段值被修改后未刷新。
        }

        private SubPanel topPanel;

        public SubPanel TopPanel
        {
            get { return topPanel; }
        }

        private SubPanel leftPanel;

        public SubPanel LeftPanel
        {
            get { return leftPanel; }
        }

        private SubPanel rightPanel;

        public SubPanel RightPanel
        {
            get { return rightPanel; }
        }

        /// <summary>
        /// 位于TopPanel和LeftPanel这两个子面板间的附加面板。
        /// </summary>
        private SubPanel tlPanel;

        public SubPanel TlPanel
        {
            get { return tlPanel; }
        }

        /// <summary>
        /// 位于TopPanel和RightPanel两个子面板间的附加面板。
        /// </summary>
        private SubPanel trPanel;

        public SubPanel TrPanel
        {
            get { return trPanel; }
        }

        /// <summary>
        /// 位于LeftPanel和RightPanel两个子面板间的附加面板。
        /// </summary>
        private SubPanel lrPanel;

        public SubPanel LrPanel
        {
            get { return lrPanel; }
        }

        private bool hideAdditionalPanels = false;

        /// <summary>
        /// 隐藏附加子面板。
        /// </summary>
        public bool HideAdditionalPanels
        {
            get { return hideAdditionalPanels; }
            set
            {
                hideAdditionalPanels = value;
                if (this.XmlData != null)
                {
                    this.XmlData.SetAttribute("HideAdditionalPanels", hideAdditionalPanels.ToString());
                }
            }
        }

        protected override void RefreshSubPanelRelatios()
        {
            this.SubPanels.Clear();// 此方法可能被重复调用。

            this.subPanels.Add(topPanel);
            this.subPanels.Add(leftPanel);
            this.subPanels.Add(rightPanel);
            this.subPanels.Add(tlPanel);
            this.subPanels.Add(trPanel);
            this.subPanels.Add(lrPanel);

            if (hideAdditionalPanels)
            {
                topPanel.BottomSubPanel = leftPanel;
                leftPanel.TopSubPanel = topPanel;
                leftPanel.RightSubPanel = rightPanel;
                rightPanel.LeftSubPanel = leftPanel;
                rightPanel.TopSubPanel = topPanel;
            }
            else
            {
                topPanel.BottomSubPanel = tlPanel;
                tlPanel.TopSubPanel = topPanel;
                tlPanel.RightSubPanel = trPanel;
                tlPanel.BottomSubPanel = leftPanel;
                leftPanel.TopSubPanel = tlPanel;
                leftPanel.RightSubPanel = lrPanel;
                lrPanel.LeftSubPanel = leftPanel;
                lrPanel.RightSubPanel = rightPanel;
                lrPanel.TopSubPanel = trPanel;
                rightPanel.TopSubPanel = trPanel;
                rightPanel.LeftSubPanel = lrPanel;
                trPanel.LeftSubPanel = tlPanel;
                trPanel.TopSubPanel = topPanel;
                trPanel.BottomSubPanel = rightPanel;
            }

            this.firstSubPanel = this.topPanel;
            this.lastSubPanel = this.rightPanel;
        }

        public override void SetProperty(string propertyName, string value)
        {
            base.SetProperty(propertyName, value);

            //switch (propertyName)
            //{
            //    case "Indent":
            //        {
            //            this.Indent = int.Parse(value);
            //            break;
            //        }
            //}
        }
    }
}
